﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using HSDc.RingleFlow.Api.Service;
using HSDc.RingleFlow.Kernel.DBPersit.Util;
using NUnit.Framework;
using HSDc.RingleFlow.Api.Rule;
using HSDc.RingleFlow.Api.Kernel;

namespace HSDc.RingleFlow.Kernel.DBPersit
{
    //[TestFixture]
    public class RepositoryServiceImpl : IRepositoryService
    {
        string IRepositoryService.RegisterProcessDefinition(string DefinitionXml)
        {
            throw new NotImplementedException();
        }

        Api.Kernel.IProcessDefinition IRepositoryService.GetProcessDefinition(string processDefinitionId)
        {
            Dao.RepositoryServiceDao dao = new Dao.RepositoryServiceDao();
            ProcessDefinitionDto dto = dao.GetProcessDefinition(processDefinitionId);
            return InitialProcessDefinition(dto, dao);
        }

        Api.Kernel.IProcessDefinition IRepositoryService.GetProcessDefinitionByName(string processDefinitionName)
        {
            Dao.RepositoryServiceDao dao = new Dao.RepositoryServiceDao();
            ProcessDefinitionDto dto = dao.GetProcessDefinitionByName(processDefinitionName);
            return InitialProcessDefinition(dto, dao);
        }

        private ProcessDefinition InitialProcessDefinition(ProcessDefinitionDto dto, Dao.RepositoryServiceDao dao)
        {
            ProcessDefinition _pd = new ProcessDefinition(dto.Definition_GUID, dto.Definition_Name, dto.Definition_Version.ToString(), dto.Definition_ACTIVE,
                dao.GetActiveProcessInstance(dto.Definition_ID));
            List<ProcessActivityDto> actDtos = dao.GetDefaultActivities(dto.Definition_ID);
            SortedDictionary<int, Activity> actDict = new SortedDictionary<int, Activity>();
            SortedDictionary<int, Transition> transDict = new SortedDictionary<int, Transition>();
            Dictionary<int, TransitionDto> transDtoDict = new Dictionary<int, TransitionDto>();
            CreateActivityAndTransition(dao, actDtos, actDict, transDict, transDtoDict);
            FillTransitionToActivity(actDict, transDict, transDtoDict);
            foreach (Activity act in actDict.Values)
            {
                _pd.AddActivity(act);
            }
            return _pd;
        }

        private static void FillTransitionToActivity(SortedDictionary<int, Activity> actDict, SortedDictionary<int, Transition> transDict, Dictionary<int, TransitionDto> transDtoDict)
        {
            Activity acin, acout = null;
            TransitionDto transDto2 = null;
            Transition trans = null;
            transDict.Reverse();
            foreach (int transId in transDict.Keys)
            {
                transDtoDict.TryGetValue(transId, out transDto2);
                transDict.TryGetValue(transId, out trans);
                actDict.TryGetValue(transDto2.Transition_Target, out acin);
                trans.AddTarget(acin);
                actDict.TryGetValue(transDto2.Transition_Source, out acout);
                acout.AddOutboundTransition(trans);
                acin.AddInboundTransition(trans);
                actDict.Remove(transDto2.Transition_Target);
                actDict.Add(transDto2.Transition_Target, acin);
                actDict.Remove(transDto2.Transition_Source);
                actDict.Add(transDto2.Transition_Source, acout);
            }
        }

        private void CreateActivityAndTransition(Dao.RepositoryServiceDao dao, List<ProcessActivityDto> actDtos, SortedDictionary<int, Activity> actDict, SortedDictionary<int, Transition> transDict, Dictionary<int, TransitionDto> transDtoDict)
        {
            Activity ac = null;
            Transition trans = null;
            foreach (ProcessActivityDto actDto in actDtos)
            {
                ac = WFObjectFactory.NewActivity(this, actDto.Activity_CLASS, new object[] { actDto.Activity_GUID, actDto.Activity_Name, 
                    (IRule)WFObjectFactory.NewRule(this, actDto.Activity_RULE_CLASS, new object[] {}), 
                    RetrieveActivitySwimlane(dao, actDto.Activity_ID)});
                actDict.Add(actDto.Activity_ID, ac);
                foreach (TransitionDto transDto in dao.GetTransitionsBySource(actDto.Activity_ID))
                {
                    trans = new Transition(ac, transDto.Transition_Constraints);
                    transDict.Add(transDto.Transition_ID, trans);
                    transDtoDict.Add(transDto.Transition_ID, transDto);
                }
            }
        }

        private Swimlane RetrieveActivitySwimlane(Dao.RepositoryServiceDao dao, int ActivityID)
        {
            SwimlaneDto dto = dao.GetActivityBelongSwimlane(ActivityID);
            return new Swimlane(dto.Swimlane_GUID, dto.Swimlane_Org_ID,
                RetrieveSwimlaneType(dao, dto.Swimlane_GUID),
                (IRule)WFObjectFactory.NewRule(this, dto.Swimlane_RULE_CLASS, new object[] { }));

        }

        private SwimlaneType RetrieveSwimlaneType(Dao.RepositoryServiceDao dao, string guid)
        {
            int orgType = dao.GetOrgType(guid);
            return (SwimlaneType)orgType;
        }

        [Test]
        public void TestInitialProcessDefinition()
        {
            Dao.RepositoryServiceDao dao = new Dao.RepositoryServiceDao();
            ProcessDefinitionDto dto = dao.GetProcessDefinition("83CEDA43-0E89-4F57-95D7-553FCF721A38");
            ProcessDefinition real = InitialProcessDefinition(dto, dao);
        }
    }
}
